visual-artifacts v1: PR 2 core phase renderers (think/review/security/qa/ship)#218
Merged
Merged
Conversation
…/ship) Wires renderers for the remaining core phases so /think, /review, /security, /qa, and /ship artifacts can each be inspected as a static HTML view. Same trust + path-safety contract as PR 1. Shared helpers in bin/lib/visual-render.sh: - nano_visual_normalize_artifact: jq-based coercion that turns a legacy or malformed artifact into a predictable shape (summary, context_checkpoint, scope_drift, findings, conflicts as objects / arrays). Every renderer reads the normalized form. - nano_visual_severity_class: maps blocking/critical/high/etc to a CSS class so review/security/qa agree on color and styling. - nano_visual_safe_pr_url: allowlist for ship pr_url. Only https://github.com/* renders as a clickable link; every other URL renders as escaped text with an explicit "host not in allowlist" note. - nano_visual_safe_screenshot_path: stricter allowlist for future QA screenshot rendering (PR 3 may wire this). Body renderers in bin/render-artifact.sh: - render_think_body: value proposition, scope mode chip, narrowest wedge, key risk, premise validation, archetype card with optional example reference, out-of-scope list. - render_review_body: 4-counter summary (blocking / should fix / nitpicks / positive), scope drift status chip with out-of-scope and missing file lists, severity-styled findings. - render_security_body: 5-counter summary (critical / high / medium / low / total), findings with category chips (OWASP A0n / STRIDE), proof_of_concept and reproduce blocks wrapped in <details><pre> so multi-line escaped content stays readable. - render_qa_body: mode / status chips, WTF likelihood, 5-counter test/bug breakdown, findings with reproduce + root_cause + fixed flag. - render_ship_body: report_only mode renders a short report card (no release-packet styling); normal mode renders PR title / number / URL / status / CI passed. Unsafe PR URLs are rendered as text with data-testid="unsafe-pr-url" so callers can audit. - render_findings_section: shared helper for review/security/qa. - render_context_checkpoint: shared helper for the trailing card. CI extensions: - 8 new e2e cells (think, review, security, qa, ship normal, ship report_only, ship malicious URL, XSS across all 5 phases). - 5 new template safety checks (nano_visual_safe_pr_url usage, rel="noopener noreferrer", nano_visual_severity_class, CSS for .finding.sev-bad and .counter). - Template safety lint now allows the `# url-allowlist` marker so the legitimate code-level case pattern does not trip the "no http(s) URLs" check. Test counts: - e2e: 86 -> 152 (66 new checks across 8 phase + XSS cells) - template safety: 20 -> 25 - Total contract surface: 177 checks
Codex PR 2 pass 1 finding. /ship's schema only requires summary to be an object, so a malformed artifact with "ci_passed":"<script>alert(1)</script>" rendered raw markup. Every other JSON-derived ship field passes through nano_html_escape; the boolean-typed ci_passed was the one gap. Pipe ci_passed through nano_html_escape like every other scalar. Adds a regression cell with a string-typed ci_passed containing a script tag; the rendered HTML must contain the escaped form and must not contain the raw tag. Test count: 152 -> 154.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR 2 of the Visual Artifacts v1 round. Wires renderers for the remaining core phases so
/think,/review,/security,/qa, and/shipartifacts can each be inspected as a static HTML view. Same trust + path-safety contract as PR 1.What changed
Shared helpers (
bin/lib/visual-render.sh)nano_visual_normalize_artifact— jq-based coercion that turns a legacy or malformed artifact into a predictable shape (summary, context_checkpoint, scope_drift, findings, conflicts as objects/arrays). Every renderer reads the normalized form.nano_visual_severity_class— mapsblocking/critical/high/ etc to a CSS class so review/security/qa agree on color.nano_visual_safe_pr_url— allowlist for shippr_url. Onlyhttps://github.com/*renders as a clickable link; every other URL renders as escaped text with an explicit "host not in allowlist" note.nano_visual_safe_screenshot_path— stricter allowlist for future QA screenshot rendering..counter,.finding.sev-bad/warn/info/ok,.chip,.pr-link,.unsafe-url.Body renderers (
bin/render-artifact.sh)render_think_body— value proposition, scope mode chip, narrowest wedge, key risk, premise validation, archetype card with optional example reference, out-of-scope list.render_review_body— 4-counter summary (blocking / should fix / nitpicks / positive), scope drift status chip with out-of-scope and missing file lists, severity-styled findings.render_security_body— 5-counter summary (critical / high / medium / low / total), findings with category chips (OWASP A0n / STRIDE),proof_of_conceptandreproduceblocks wrapped in<details><pre>.render_qa_body— mode / status chips, WTF likelihood, 5-counter test/bug breakdown, findings with reproduce + root cause + fixed flag.render_ship_body—report_onlymode renders a short report card (no release-packet styling); normal mode renders PR title / number / URL / status / CI passed. Unsafe PR URLs render as text withdata-testid="unsafe-pr-url".render_findings_section— shared helper for review/security/qa.render_context_checkpoint— shared helper for the trailing card.CI extensions
nano_visual_safe_pr_urlusage,rel="noopener noreferrer",nano_visual_severity_class, CSS classes.# url-allowlistmarker so the legitimate case pattern does not trip the "no http(s) URLs" check.Test counts
ci/e2e-visual-artifacts.shci/check-visual-artifact-templates.shCodex review trail (2 passes, clean)
ci_passednot escaped (boolean-typed in schema, but artifact may store string)nano_html_escapelike every other scalarTest plan
ci/e2e-visual-artifacts.sh154/154ci/check-visual-artifact-templates.sh25/25<script>/<img onerror>/<iframe>fixturesjavascript:alert(1)) renders as escaped text only, never as<a href>report_onlymode shows the report card and omits the release-packet header